import 'package:flutter/material.dart' show BuildContext, Size;
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:utils/plugins/flutter_utils.dart';
import 'package:utils/util/print.dart';

export 'package:flutter_screenutil/size_extension.dart';

class Density {
  static Density _instance = Density._internal();

  /// TODO 是否需要重新计算。true不需要重新计算，否则需要进行重新计算
  bool _needCal;
  double _screenWidth = 0;
  double _screenHeight = 0;
  double _ratio = 0.0;

  static int _designWidth = 720;
  static int _designHeight = 1280;
  Map<double, double> _result;

  factory Density() {
    return _instance;
  }

  Density._internal() {
    _result = {};
  }

  void destroy() {
    _result?.clear();
    _result = null;
    _ratio = 0.0;
  }

  void init({int designWidth = 720, int designHeight = 1280}) async {
    _designWidth = designWidth;
    _designHeight = designHeight;
    await _initScreenSize();
    Print().printNative(
        "_screenWidth($_screenWidth) _screenHeight($_screenHeight)");
  }

  /// TODO 初始化屏幕尺寸
  Future<void> _initScreenSize() async {
    _screenWidth = await FlutterUtils.getScreenWidth();
    _screenHeight = await FlutterUtils.getScreenHeight();
    _needCal = true;
    Print().printNative("初始化屏幕尺寸 是否需要重新计算屏幕密度($_needCal) true表示不需要重新计算屏幕密度");
  }

  /// TODO 是否需要重新计算。
  /// true 需要重新计算，
  /// 否则不需要进行重新计算
  bool isNeedReCall() {
    return _needCal != true;
  }

  Future<double> ratio() async {
    if (isNeedReCall()) {
      await _initScreenSize();
      _result?.clear();
      _ratio = null;
    }
    if (_ratio == null || _ratio == 0.0) {
      double wRatio = calWidthRatio();
      double hRatio = calHeightRatio();
      _result?.clear();
      Print().printNative(
          "_screenWidth($_screenWidth) _wRatio($wRatio) _screenHeight($_screenHeight) _hRatio($hRatio)");
      _ratio = Math.min(wRatio, hRatio);
    }
    return _ratio;
  }

  double calWidthRatio() {
    return _screenWidth / _designWidth;
  }

  double calHeightRatio() {
    return _screenHeight / _designHeight;
  }

  Future<double> autoPx(double px) async {
    if (_result == null) {
      _result = Map();
    }
    if (!isNeedReCall() && _result.containsKey(px)) {
      return _result[px];
    }
    double _px = px * await ratio();
    if (!isNeedReCall()) {
      _result[px] = _px;
      return _px;
    }
    return px / 2;
  }
}
